﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using MQTTnet;
using MQTTnet.Server;
using MQTTnet.Protocol;
using ServiceStack;
using ServiceStack.Text.Common;
using System.IO;

namespace mqttserver
{
    public partial class Form1 : Form
    {
        private IMqttServer _mqttServer = null;
        private Action<string> _updateListBoxAction;

        //StreamWriter log_file = new StreamWriter("log_file", true); /* 日志文件 */

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var ips = Dns.GetHostAddressesAsync(Dns.GetHostName());

            foreach (var ip in ips.Result)
            {
                switch (ip.AddressFamily)
                {
                    case AddressFamily.InterNetwork:
                        ServerIP_text.Text = ip.ToString();
                        break;
                    case AddressFamily.InterNetworkV6:
                        break;
                }
            }

            _updateListBoxAction = new Action<string>((s) =>
            {
                display_text.AppendText(s);
                display_text.AppendText("\r\n");
                /* 以下这部分代码搞不清是做什么用的 */
                //listBox1.Items.Add(s);
                //if (listBox1.Items.Count > 1000)
                //{
                //    listBox1.Items.RemoveAt(0);
                //}
                //var visibleItems = listBox1.ClientRectangle.Height / listBox1.ItemHeight;

                //listBox1.TopIndex = listBox1.Items.Count - visibleItems + 1;
            });

            display_text.Enabled = false;
            Stop_button.Enabled = false;
            Port_text.Text = "1883";
            Port_text.Enabled = false;
            ServerIP_text.Enabled = false;
        }



        private async void MqttServer()
        {
            if (null != _mqttServer)
            {
                return;
            }

            var optionBuilder = new MqttServerOptionsBuilder().WithConnectionBacklog(1000).WithDefaultEndpointPort(Convert.ToInt32(Port_text.Text));

            if (!ServerIP_text.Text.IsNullOrEmpty())
            {
                optionBuilder.WithDefaultEndpointBoundIPAddress(IPAddress.Parse(ServerIP_text.Text));
            }

            var options = optionBuilder.Build();

            (options as MqttServerOptions).ConnectionValidator += context =>
            {
                if (context.ClientId.Length < 10)
                {
                    context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
                    return;
                }
                if (!context.Username.Equals("admin"))
                {
                    context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                    return;
                }
                if (!context.Password.Equals("public"))
                {
                    context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                    return;
                }
                context.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;

            };

            _mqttServer = new MqttFactory().CreateMqttServer();
            _mqttServer.ClientConnected += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, $">Client Connected:ClientId:{args.ClientId},ProtocalVersion:");

                var s = _mqttServer.GetClientSessionsStatusAsync();
                connect_num.BeginInvoke(new Action(() => { connect_num.Text = $"连接总数：{s.Result.Count}"; }));
                //log_file.WriteLine("有新的连接，ClientId:" + args.ClientId);
                //log_file.WriteLine("连接总数为:" + s.Result.Count.ToString());
                //log_file.Flush();
            };

            _mqttServer.ClientDisconnected += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, $"<Client DisConnected:ClientId:{args.ClientId}");
                var s = _mqttServer.GetClientSessionsStatusAsync();
                connect_num.BeginInvoke(new Action(() => { connect_num.Text = $"连接总数：{s.Result.Count}"; }));

                //log_file.WriteLine("有连接断开，ClientId:" + args.ClientId);
                //log_file.WriteLine("剩余连接总数为:" + s.Result.Count.ToString());
                //log_file.Flush();
            };

            _mqttServer.ApplicationMessageReceived += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction,
                    $"ClientId:{args.ClientId} Topic:{args.ApplicationMessage.Topic} Payload:{Encoding.UTF8.GetString(args.ApplicationMessage.Payload)} QualityOfServiceLevel:{args.ApplicationMessage.QualityOfServiceLevel}");

                //log_file.WriteLine("接收到的消息," + "主题:" + args.ApplicationMessage.Topic + "  Payload:" + Encoding.UTF8.GetString(args.ApplicationMessage.Payload) + "  等级:" + args.ApplicationMessage.QualityOfServiceLevel);
                //log_file.Flush();
            };

            _mqttServer.ClientSubscribedTopic += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, $"@ClientSubscribedTopic ClientId:{args.ClientId} Topic:{args.TopicFilter.Topic} QualityOfServiceLevel:{args.TopicFilter.QualityOfServiceLevel}");
                //log_file.WriteLine("接收到的订阅," + "订阅clinet ID:" + args.ClientId + "  订阅主题为:" + args.TopicFilter.Topic + "  订阅等级为:" + args.TopicFilter.QualityOfServiceLevel);
            };
            _mqttServer.ClientUnsubscribedTopic += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, $"%ClientUnsubscribedTopic ClientId:{args.ClientId} Topic:{args.TopicFilter.Length}");
                //log_file.WriteLine("取消的订阅," + "订阅clinet ID:" + args.ClientId + "  主题长度为:" + args.TopicFilter.Length);
            };

            _mqttServer.Started += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, "Mqtt Server Start...");
            };

            _mqttServer.Stopped += (sender, args) =>
            {
                display_text.BeginInvoke(_updateListBoxAction, "Mqtt Server Stop...");

            };
            await _mqttServer.StartAsync(options);
        }

        private void Start_button_Click(object sender, EventArgs e)
        {
            MqttServer();
            Start_button.Enabled = false;
            Stop_button.Enabled = true;

            ServerIP_text.Enabled = false;
            Port_text.Enabled = false;
        }

        private void Stop_button_Click(object sender, EventArgs e)
        {
            if (null != _mqttServer)
            {
                foreach (var clientSessionStatuse in _mqttServer.GetClientSessionsStatusAsync().Result)
                {
                    clientSessionStatuse.DisconnectAsync();
                }
                _mqttServer.StopAsync();
                _mqttServer = null;
            }
            Start_button.Enabled = true;
            Stop_button.Enabled = false;

            ServerIP_text.Enabled = true;
            Port_text.Enabled = true;
        }

        private void display_text_TextChanged(object sender, EventArgs e)
        {
            display_text.SelectionStart = display_text.Text.Length;
            display_text.ScrollToCaret();
        }
    }
}
